Webframeworkk/ASP.NET Core/Entity Framework Core
Dieses Tutorial bietet einen umfassenden Überblick über Entity Framework Core (EF Core), das moderne, leichtgewichtige und plattformübergreifende Object-Relational Mapper (ORM) Framework für .NET.
1. Einführung in EF Core
EF Core vereinfacht die Interaktion mit Datenbanken, indem es Ihnen ermöglicht, mit Daten als .NET-Objekte (Entities) zu arbeiten, anstatt rohe SQL-Abfragen zu schreiben.
Vorteile:
- Produktivität: Weniger Boilerplate-Code für Datenbankoperationen.
- Objektorientiert: Nutzung vertrauter C#-Konzepte.
- Typsicherheit: LINQ-Abfragen werden zur Kompilierzeit geprüft.
- Plattformübergreifend: Unterstützt SQL Server, SQLite, PostgreSQL, MySQL usw.
Nachteile:
- Abstraktions-Overhead: Kann bei komplexen Abfragen weniger effizient sein als handgeschriebenes SQL.
- Lernkurve: Erfordert Verständnis der internen Funktionsweise für optimale Performance.
2. Die Architektur: Ein Drei-Schichten-Modell
- Konzeptionelles Modell (Entity Model): Ihre C#-Klassen, die das Datenbankschema repräsentieren.
- Mapping: Die Brücke zwischen Ihren Klassen und der Datenbank (konfiguriert über Data Annotations oder Fluent API).
- Speichermodell (Database Schema): Die tatsächliche Struktur in der Datenbank (Tabellen, Spalten, Constraints).
3. DbContext und DbSet
Der DbContext ist das Herzstück von EF Core. Er fungiert als Sitzung mit der Datenbank.
Hauptaufgaben:
- Verbindungsmanagement.
- Änderungsverfolgung (Change Tracking).
- Übersetzung von LINQ in SQL.
Beispiel: PersonsDbContext
public class PersonsDbContext : DbContext
{
public PersonsDbContext(DbContextOptions options) : base(options) { }
public DbSet<Country> Countries { get; set; }
public DbSet<Person> Persons { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Country>().ToTable("Countries");
modelBuilder.Entity<Person>().ToTable("Persons");
}
}
4. Connection Strings
Connection Strings definieren, wo sich Ihre Datenbank befindet und wie darauf zugegriffen wird.
Empfohlener Speicherort: appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=PersonsDatabase;Integrated Security=True;"
}
}
Registrierung in Program.cs:
builder.Services.AddDbContext<PersonsDbContext>(options => {
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
5. Entwicklungsansätze
- Code-First: Sie schreiben C#-Klassen, EF Core erstellt die Datenbank. Ideal für neue Projekte.
- Database-First: Sie starten mit einer bestehenden Datenbank, EF Core generiert die Klassen. Ideal für Legacy-Systeme.
6. Migrationen und Seed-Daten
Migrationen ermöglichen es, Schemaänderungen versioniert zu verwalten.
Wichtige Befehle (Package Manager Console):
Add-Migration InitialCreate: Erstellt ein Skript für die aktuellen Modelländerungen.Update-Database: Wendet die Migrationen auf die Datenbank an.
Seed-Daten (Initialdaten): Nutzen Sie HasData in OnModelCreating, um Tabellen vorab zu befüllen (z. B. Länderlisten).
modelBuilder.Entity<Country>().HasData(
new Country() { CountryID = Guid.NewGuid(), CountryName = "Deutschland" }
);
7. Fluent API vs. Data Annotations
Während Data Annotations ([Key], [Required]) einfach sind, bietet die Fluent API mehr Flexibilität direkt im DbContext.
Beispiel Fluent API:
modelBuilder.Entity<Person>()
.Property(p => p.TIN)
.HasColumnName("TaxIdentificationNumber")
.HasColumnType("varchar(8)")
.IsRequired();
8. CRUD-Operationen im Controller
Dank EF Core lassen sich Datenbankzugriffe schlank im Service-Layer implementieren.
Beispiel: Person hinzufügen (Create)
public async Task<PersonResponse> AddPerson(PersonAddRequest personRequest)
{
Person person = personRequest.ToPerson();
person.PersonID = Guid.NewGuid();
_db.Persons.Add(person);
await _db.SaveChangesAsync();
return person.ToPersonResponse();
}
Eager Loading mit Include(): Um verwandte Daten (z. B. das Land einer Person) sofort mitzuladen:
var persons = await _db.Persons.Include(p => p.Country).ToListAsync();
9. Fortgeschrittene Funktionen
Stored Procedures EF Core erlaubt die Ausführung von Stored Procedures über FromSqlRaw (für Abfragen) oder ExecuteSqlRaw (für Befehle).
var persons = _db.Persons.FromSqlRaw("EXECUTE [dbo].[GetAllPersons]").ToList();
Berichterstellung (PDF & CSV)
- PDF: Mit Bibliotheken wie Rotativa können Razor-Views direkt als PDF gerendert werden (
return new ViewAsPdf(...)). - CSV: Mit CsvHelper können Daten effizient in Streams geschrieben werden.
10. Best Practices & Tipps
- Asynchrone Programmierung: Nutzen Sie immer
ToListAsync(),SaveChangesAsync()etc., um die Skalierbarkeit zu erhöhen. - Thin Controllers: Lagern Sie die EF-Logik in separate Service-Klassen aus.
- DTOs nutzen: Verwenden Sie
Request- undResponse-Modelle, um Ihre Datenbank-Entities vor der UI zu verbergen. - Referenzielle Integrität: Achten Sie auf Primär- und Fremdschlüssel-Konfigurationen, um Datenkonsistenz zu wahren.
Tutorial erstellt für Thorsten - Viel Erfolg bei der Entwicklung mit ASP.NET Core MVC!